/***************************************************
 * Author:		Xycaleth
 * Description:	Source code for player classes.
 * Revision:	$Id: bg_classes.c 5 2008-09-14 11:12:15Z xycaleth $
 **************************************************/

#include "../NDA_Server/S_Header.h"
#include "bg_classes.h"
#include "bg_public.h"

playerClassInfo_t	playerClasses[MAX_PLAYER_CLASSES];

#define MAX_CLASS_FILE_SIZE	4096

char	tempClassFileData[MAX_CLASS_FILE_SIZE] = { 0 };

void NDA_DefaultClassData ( playerClassInfo_t *pci )
{
	Q_strncpyz (pci->name, "unnamed class", sizeof (pci->name));
	Q_strncpyz (pci->model, "kyle", sizeof (pci->model));

	pci->start_hp = 100;
	pci->max_hp = 100;

	pci->start_ap = 0;
	pci->max_ap = 0;

	pci->mp = 0;

	pci->special_skills = 0;
	pci->speed_multiplier = 1.0f;

	pci->allowed_weapons = (1 << WP_MELEE);
	pci->allowed_magic = 0;
}

extern qboolean BG_ParseLiteral ( const char **data, const char *string );
extern stringID_table_t FPTable[];
extern stringID_table_t WPTable[];
qboolean NDA_ParseClassFile ( const int classNum, const char *className )
{
	char		*p;
	const char	*token;
	const char	*value;
	int		n;

	p = &tempClassFileData[0];
	COM_BeginParseSession ("ClassInfo");

	while ( p )
	{
		token = COM_ParseExt (&p, qtrue);
		if ( !token[0] || token == NULL )
		{
			return qfalse;
		}

		if ( Q_stricmpn (token, "ClassInfo", 9) == 0 )
		{
			break;
		}

		SkipBracedSection (&p);
	}

	if ( !p )
	{
		// We didn't find our ClassInfo section
		return qfalse;
	}

	if ( BG_ParseLiteral (&p, "{") )
	{
		return qfalse;
	}

	playerClasses[classNum].id = classNum;
	NDA_DefaultClassData (&playerClasses[classNum]);

	while ( 1 )
	{
		token = COM_ParseExt (&p, qtrue);
		if ( !token[0] || token == NULL )
		{
			Com_Printf (S_COLOR_RED "ERROR: unexpected EOF while parsing class file '%s'\n", className);
			return qfalse;
		}

		if ( Q_stricmp (token, "}") == 0 )
		{
			break;
		}
		
		if ( Q_stricmp (token, "name") == 0 )
		{
			if ( COM_ParseString (&p, &value) )
			{
				continue;
			}
			
			Q_strncpyz (playerClasses[classNum].name, value, sizeof (playerClasses[classNum].name));
		}
		else if ( Q_stricmp (token, "model") == 0 )
		{
			if ( COM_ParseString (&p, &value) )
			{
				continue;
			}
			
			Q_strncpyz (playerClasses[classNum].model, value, sizeof (playerClasses[classNum].model));
		}
		else if ( Q_stricmp (token, "startarmor") == 0 )
		{
			if ( COM_ParseInt (&p, &n) )
			{
				SkipRestOfLine (&p);
				continue;
			}
			
			playerClasses[classNum].start_ap = n;
		}
		else if ( Q_stricmp (token, "maxarmor") == 0 )
		{
			if ( COM_ParseInt (&p, &n) )
			{
				SkipRestOfLine (&p);
				continue;
			}
			
			playerClasses[classNum].max_ap = n;
		}
		else if ( Q_stricmp (token, "starthealth") == 0 )
		{
			if ( COM_ParseInt (&p, &n) )
			{
				SkipRestOfLine (&p);
				continue;
			}
			
			playerClasses[classNum].start_hp = n;
		}
		else if ( Q_stricmp (token, "maxhealth") == 0 )
		{
			if ( COM_ParseInt (&p, &n) )
			{
				SkipRestOfLine (&p);
				continue;
			}
			
			playerClasses[classNum].max_hp = n;
		}
		else if ( Q_stricmp (token, "magicpoints") == 0 )
		{
			if ( COM_ParseInt (&p, &n) )
			{
				SkipRestOfLine (&p);
				continue;
			}
			
			playerClasses[classNum].mp = n;
		}
		else if ( Q_stricmp (token, "weapons") == 0 )
		{
			int	weapon;

			if ( COM_ParseString (&p, &value) )
			{
				continue;
			}
			
			weapon = GetIDForString (WPTable, value);
			playerClasses[classNum].allowed_weapons |= (1 << weapon);
		}
		else if ( Q_stricmp (token, "magicabilities") == 0 )
		{
			int	ability = 0;

			if ( COM_ParseString (&p, &value) )
			{
				continue;
			}
			
			//ability = GetIDForString (MPTable, value);
			playerClasses[classNum].allowed_magic |= (1 << ability);
		}
		else if ( Q_stricmp (token, "skills") == 0 )
		{
			int	skill = 0;

			if ( COM_ParseString (&p, &value) )
			{
				continue;
			}
			
			//skill = GetIDForString (SkillsTable, value);
			playerClasses[classNum].special_skills |= (1 << skill);
		}
		else if ( Q_stricmp (token, "speed") == 0 )
		{
			float	f;

			if ( COM_ParseFloat (&p, &f) )
			{
				SkipRestOfLine (&p);
				continue;
			}
			
			playerClasses[classNum].speed_multiplier = f;
		}
		else
		{
			SkipRestOfLine (&p);
		}
	}

	return qtrue;
}

extern int trap_FS_FOpenFile ( const char *qpath, fileHandle_t *f, fsMode_t mode );
extern int trap_FS_GetFileList ( const char *path, const char *extension, char *listbuf, int bufsize );
extern void trap_FS_FCloseFile ( fileHandle_t f );
extern void trap_FS_Read ( void *buffer, int len, fileHandle_t f );
extern void trap_Cvar_Set ( const char *var_name, const char *value );
void NDA_LoadClasses ( void )
{
	int		numFiles = 0, i, strLen = 0, fileLen = 0, compressedLen = 0;
	int		classCount = 0;
	char		classFilesList[2048] = { 0 };
	char		*holdChar = classFilesList;
	fileHandle_t	f;

	memset (playerClasses, 0, sizeof (playerClassInfo_t) * MAX_PLAYER_CLASSES);

#ifdef _DEBUG
	Com_Printf ("Loading NDA classes...");
#endif

	numFiles = trap_FS_GetFileList ("ext_data/NDA/classes", ".cls", classFilesList, sizeof (classFilesList));
	if ( numFiles <= 0 )
	{
		// Oh dear...we haven't got any classes at all?!
		Com_Error (ERR_DROP, "No player classes found.\n");
		return;
	}
	else if ( numFiles >= MAX_PLAYER_CLASSES )
	{
		numFiles = MAX_PLAYER_CLASSES;
		Com_Printf ("Too many classes. Only loading first %d classes.\n", MAX_PLAYER_CLASSES);
	}

	for ( i = 0; i < numFiles; ++i, holdChar += strLen + 1 )
	{
		strLen = strlen (holdChar);

		fileLen = trap_FS_FOpenFile (va ("ext_data/NDA/classes/%s", holdChar), &f, FS_READ);
		if ( fileLen == -1 )
		{
			Com_Printf ("Unable to read file ext_data/NDA/classes/%s.\n", holdChar);
		}
		else if ( fileLen >= MAX_CLASS_FILE_SIZE )
		{
			Com_Printf ("Class file ext_data/NDA/classes/%s is too large (%d bytes, max. %d bytes).\n", holdChar, fileLen, MAX_CLASS_FILE_SIZE);
			break;
		}
		else
		{
#ifdef _DEBUG
			Com_Printf ("Found class file %s\n", holdChar);
#endif

			trap_FS_Read (tempClassFileData, fileLen, f);
			trap_FS_FCloseFile (f);

			tempClassFileData[fileLen] = 0;

			compressedLen = COM_Compress (tempClassFileData);
			tempClassFileData[compressedLen] = 0;

			if ( NDA_ParseClassFile (classCount, holdChar) )
			{
				++classCount;
			}
		}
	}

	memset (tempClassFileData, 0, sizeof (tempClassFileData));

	if ( classCount <= 0 )
	{
		// We don't have any VALID player classes...shut down the server!
		Com_Error (ERR_DROP, "No player classes found.\n");
	}
}

// eof
